detection()
{
    
    
    vector start = llGetPos();
    
    // rotation camRot = llGetCameraRot();
    // vector camPos = llGetCameraPos();
    
    // to-do: point slightly downwards
        
    rotation objectRot = llGetRootRotation() * llEuler2Rot(<0.0, -45.0 * DEG_TO_RAD, 0.0>);   
    rotation castRot = llGetRootRotation() * llEuler2Rot(<0.0, 45.0 * DEG_TO_RAD, 0.0>);   

    llSetRot(objectRot);            

    llOwnerSay("Debug: Object rot: " + (string) objectRot
        + " Root rot: " + (string) llGetRootRotation());
    // + " Camera rot: "
    //    + (string) camRot + " Camera pos: " + (string) camPos);
        
    // llSetLinkPrimitiveParamsFast(2, [PRIM_ROT_LOCAL, objectRot]); // set prim to point slightly downwards
     list results = llCastRay(start, start + <25.0, 0.0, 0.0> * castRot, [
        RC_DATA_FLAGS, RC_GET_ROOT_KEY,
        RC_REJECT_TYPES, RC_REJECT_LAND,
        RC_MAX_HITS, 50,
        RC_DETECT_PHANTOM, TRUE
    ]);
 
    integer statusCode = llList2Integer(results, -1);
    
    if (statusCode == RCERR_SIM_PERF_LOW)
    {
        llOwnerSay("Sim performance low, cannot use llRayCast()");
    } 
    else if (statusCode == RCERR_CAST_TIME_EXCEEDED)
    {
        llOwnerSay("Too many raycasts");
    }
    else
    {
        llOwnerSay("Detected: " + llDumpList2String(results, "|"));
    
        integer hitNum;
        
        for (hitNum = 0; hitNum < statusCode; hitNum++)
        {
            key uuid = llList2Key(results, 2*hitNum);
            vector pos = llList2Vector(results, 2*hitNum+1);
            float dist = llVecDist(start, pos);
            string name;
            if (uuid == NULL_KEY)
            {
                llOwnerSay("Land at " + (string)dist + "m");
            }
            else
            {
                name = llKey2Name(uuid);
                llOwnerSay(name + "<" + (string) uuid + "> at " + (string)dist + "m");
            }
        }
    }
}

default
{
    state_entry()
    {
        llSay(0, "Script running");
        llSetTimerEvent(30.0);
        llRequestPermissions(llGetOwner(), PERMISSION_CONTROL_CAMERA|PERMISSION_TRACK_CAMERA);
        
        // laser beam
        llParticleSystem([
            PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE, 
            PSYS_SRC_BURST_PART_COUNT,(integer) 4,   // adjust for beam strength,
            PSYS_SRC_BURST_RATE,(float) .05,          
            PSYS_PART_MAX_AGE,(float)  1.2,  // was .6          
            PSYS_SRC_BURST_SPEED_MIN,(float)1,        
            PSYS_SRC_BURST_SPEED_MAX,(float) 7.0,      
            PSYS_PART_START_SCALE,(vector) <0,.1,0>, 
            PSYS_PART_END_SCALE,(vector) <.04,.5,0>,   
            PSYS_PART_START_COLOR,(vector) <1,0,0>,  
            PSYS_PART_END_COLOR,(vector) <.2,0,0>,   
            PSYS_PART_START_ALPHA,(float)0.5,          
            PSYS_PART_END_ALPHA,(float)0.00,          
            PSYS_PART_FLAGS,
            PSYS_PART_EMISSIVE_MASK |     
            PSYS_PART_FOLLOW_VELOCITY_MASK |
            PSYS_PART_FOLLOW_SRC_MASK |   
            PSYS_PART_INTERP_SCALE_MASK ]
        );
    }
    
    state_exit()
    {
        llParticleSystem([]);
    }
    
    on_rez(integer start_param)
    {
        llResetScript();
    }
   
    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_CONTROL_CAMERA)
        {
            
            llClearCameraParams();
            /* llSetCameraParams([
        CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
        CAMERA_BEHINDNESS_ANGLE, 0.0, // (0 to 180) degrees was 45
        CAMERA_BEHINDNESS_LAG, 0.0, // (0 to 3) seconds was 0.5
        CAMERA_DISTANCE, 0.5, // ( 0.5 to 10) meters was 8
        //CAMERA_FOCUS, <0,0,5>, // region relative position
        CAMERA_FOCUS_LAG, 0.0 , // (0 to 3) seconds was 0.05
        CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
        CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
        CAMERA_PITCH, 0.0, // (-45 to 80) degrees was 20
        //CAMERA_POSITION, <0,0,0>, // region relative position
        CAMERA_POSITION_LAG, 0.1, // (0 to 3) seconds
        CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
        CAMERA_POSITION_THRESHOLD, 0.0, // (0 to 4) meters
        CAMERA_FOCUS_OFFSET, <1.0,0.0,1.0> // <-10,-10,-10> to <10,10,10> meters was 3,0,2
        ]);
        */
        }
    }
    
    touch(integer who)
    {
        if (llDetectedKey(0) == llGetOwner())
            detection();
    }
    
    timer()
    {
        llOwnerSay("Timer");
        detection();
    }
    
    link_message(integer sender_num, integer num, string str, key id)
    {
        if (num == 999)
            detection();
    }
}
